🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / core / service / src / androidMain / kotlin / org / meshtastic / core / service / ServiceForegroundPromotion.kt
Displaying Raw • Download
core/service/src/androidMain/kotlin/org/meshtastic/core/service/ServiceForegroundPromotion.kt bd2863243bab6eb213401d949839a2bc74dde7e2 (bd286324) Text, 3.89 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tf0883e@fileTb4b4b4:Te6edf3SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooGenericExceptionCaughtTa5d6ff"Tb4b4b4)
Tff7b72package T7ee787org.meshtastic.core.service
Tff7b72import T7ee787android.app.Notification
Tff7b72import T7ee787android.app.Service
Tff7b72import T7ee787androidx.core.app.ServiceCompat
Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787org.meshtastic.core.repository.SERVICE_NOTIFY_ID
T8b949e/**
* Promotes [this] service to the foreground, returning whether it actually got there.
*
* The boolean is the whole point. Every caller of `startForegroundService()` leaves ActivityManager holding a
* pending-start watchdog against the service; letting a failure return quietly is what turns a recoverable
* `ForegroundServiceStartNotAllowedException` into a fatal `ForegroundServiceDidNotStartInTimeException` five seconds
* later. A false result obliges the caller to stop the service immediately.
*
* `IllegalStateException` is the supertype of the API 31+ `ForegroundServiceStartNotAllowedException` and of the API
* 34+ invalid/missing-type exceptions, so catching it covers all of them without an API-gated class reference.
*/
Tff7b72internal Tff7b72fun Te6edf3ServiceTb4b4b4.Td2a8ffstartForegroundSafelyTb4b4b4(Te6edf3notificationTb4b4b4: Te6edf3NotificationTb4b4b4, Te6edf3foregroundServiceTypeTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72= Tff7b72try Tb4b4b4{
Te6edf3ServiceCompatTb4b4b4.Te6edf3startForegroundTb4b4b4(Tff7b72thisTb4b4b4, Te6edf3SERVICE_NOTIFY_IDTb4b4b4, Te6edf3notificationTb4b4b4, Te6edf3foregroundServiceTypeTb4b4b4)
Tff7b72true
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3IllegalStateExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3exTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffForeground start not allowed by the OSTa5d6ff" Tb4b4b4}
Tff7b72false
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3SecurityExceptionTb4b4b4) Tb4b4b4{
Te6edf3retryWithoutRefusedTypeTb4b4b4(Te6edf3exTb4b4b4, Te6edf3notificationTb4b4b4, Te6edf3foregroundServiceTypeTb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3IllegalArgumentExceptionTb4b4b4) Tb4b4b4{
T8b949e// AOSP surfaces a refused type as SecurityException, but a type/manifest mismatch (or OEM variance in how the
T8b949e// refusal is reported) arrives as IllegalArgumentException. connectedDevice is always manifest-declared, so the
T8b949e// same fallback applies.
Te6edf3retryWithoutRefusedTypeTb4b4b4(Te6edf3exTb4b4b4, Te6edf3notificationTb4b4b4, Te6edf3foregroundServiceTypeTb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3exTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffError starting foreground serviceTa5d6ff" Tb4b4b4}
Tff7b72false
Tb4b4b4}
T8b949e/**
* Handles a refused foreground-service type ([SecurityException] on AOSP, [IllegalArgumentException] on a type/manifest
* mismatch) by dropping back to `connectedDevice` alone, which carries no while-in-use restriction and is always
* declared in the manifest. Only the additive `location` type can be refused this way, so when it was not requested
* there is nothing left to give up.
*/
Tff7b72private Tff7b72fun Te6edf3ServiceTb4b4b4.Td2a8ffretryWithoutRefusedTypeTb4b4b4(
Te6edf3exTb4b4b4: Te6edf3RuntimeExceptionTb4b4b4,
Te6edf3notificationTb4b4b4: Te6edf3NotificationTb4b4b4,
Te6edf3requestedTypeTb4b4b4: Tffa657IntTb4b4b4,
Tb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3fallbackType Tff7b72= Te6edf3ForegroundStartPolicyTb4b4b4.Te6edf3fallbackForegroundServiceTypeTb4b4b4(Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3requestedType Tff7b72=Tff7b72= Te6edf3fallbackTypeTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3exTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffForeground start refused with no additive type to dropTa5d6ff" Tb4b4b4}
Tff7b72return Tff7b72false
Tb4b4b4}
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3exTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffForeground start refused with type Tffd700$Te6edf3requestedTypeTa5d6ff, retrying as connectedDeviceTa5d6ff" Tb4b4b4}
Tff7b72return Te6edf3retryForegroundAsConnectedDeviceTb4b4b4(Te6edf3notificationTb4b4b4, Te6edf3fallbackTypeTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Te6edf3ServiceTb4b4b4.Td2a8ffretryForegroundAsConnectedDeviceTb4b4b4(Te6edf3notificationTb4b4b4: Te6edf3NotificationTb4b4b4, Te6edf3fallbackTypeTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72= Tff7b72try Tb4b4b4{
Te6edf3ServiceCompatTb4b4b4.Te6edf3startForegroundTb4b4b4(Tff7b72thisTb4b4b4, Te6edf3SERVICE_NOTIFY_IDTb4b4b4, Te6edf3notificationTb4b4b4, Te6edf3fallbackTypeTb4b4b4)
Tff7b72true
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3retryExTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3retryExTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffFailed to start foreground service even after retryTa5d6ff" Tb4b4b4}
Tff7b72false
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.04s